#ifndef __SHELL_H_
#define __SHELL_H_

#ifdef __cplusplus
extern "C"
{
#endif

#include "system.h"


#ifdef CONFIG_SHELL_ENABLE

#define SHELL_VERSION "1.0.0"

/* shell func call table */
typedef int (*shell_call_func_def)(int argc, char **argv);
typedef struct
{
    const char *name;       /* the name of shell call */
    const char *desc;       /* description of shell call */
    shell_call_func_def func;   /* the function address of shell call */
} _shell_call_func_obj;

/* shell variable call table */
typedef struct
{
    const char *name;       /* the name of variable */
    const char *desc;       /* description of shell variable */
    uint8_t type; /* the type of variable */
    void *var;    /* the address of variable */
} _sehll_call_var_obj;


#ifndef SHELL_SECTION
    #if defined(__CC_ARM) || defined(__CLANG_ARM)
        #define SHELL_SECTION(x)                __attribute__((section(x)))
    #elif defined (__IAR_SYSTEMS_ICC__)
        #define SHELL_SECTION(x)                @ x
    #elif defined(__GNUC__)
        #define SHELL_SECTION(x)                __attribute__((section(x)))
    #else
        #define SHELL_SECTION(x)
    #endif
#endif

#define SHELL_FUNCTION_EXPORT_CMD(name, cmd, desc)                      \
    const char __fsym_##cmd##_name[] = #cmd;    \
    const char __fsym_##cmd##_desc[] = #desc;   \
    __attribute__((used)) const _shell_call_func_obj __fsym_##cmd SHELL_SECTION("FSymTab")= \
    {                           \
        __fsym_##cmd##_name,    \
        __fsym_##cmd##_desc,    \
        (shell_call_func_def)name     \
    };

#define SHELL_VAR_EXPORT(name, type, desc)                              \
    const char __vsym_##name##_name[] = #name;  \
    const char __vsym_##name##_desc[] = #desc;  \
    __attribute__((used)) const _shell_call_func_obj __vsym_##name SHELL_SECTION("VSymTab")= \
    {                           \
        __vsym_##name##_name,   \
        __vsym_##name##_desc,   \
        type,                   \
        (void*)&name            \
    };


/**
 * @ingroup shell
 *
 * This macro exports a command to module shell.
 *
 * @param command the name of command.
 * @param desc the description of command, which will show in help.
 */
#define SHELL_CMD_EXPORT(func, desc)   \
    SHELL_FUNCTION_EXPORT_CMD(func, __cmd_##func, desc)
#define SHELL_CMD_EXPORT_ALIAS(func, alias, desc)  \
    SHELL_FUNCTION_EXPORT_CMD(func, __cmd_##alias, desc)
#endif

/* export func */

int shell_init(void);


#ifdef __cplusplus
}
#endif

#endif // __SHELL_H_
